package main;//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

import static main.Register.*;


public class Game extends Canvas implements Runnable {
    private static final long serialVersionUID = 1L;

    private boolean running;
    public static Random random;


    public static int randInt(int min, int max) {
        return random.nextInt(max - min + 1) + min;
    }
    public static final float k = 1.8f;

    public static final int WORLD_WIDTH = 2048;
    public static final int WORLD_HEIGHT = 2048;
    public static final int WIDTH = (int) (1024 * k);
    public static final int HEIGHT = (int) (512 * k);

    public static String NAME = "2d.0.1";

    public static boolean VK_LEFT = false;
    public static boolean VK_RIGHT = false;
    public static boolean VK_UP = false;
    public static boolean VK_DOWN = false;
    public static boolean VK_A = false;
    public static boolean VK_W = false;
    public static boolean VK_D = false;
    public static boolean VK_S = false;
    public static boolean debug = false;
    public static boolean RIDE = false;
    public static boolean ACCELERATION = false;

    public void start() {
        running = true;
        new Thread(this).start();
    }

    public void run() {
        long lastTime = System.currentTimeMillis();
        long delta;

        init();

        while (running) {
            delta = System.currentTimeMillis() - lastTime;
            lastTime = System.currentTimeMillis();
            render(System.currentTimeMillis());
            try {
                update(delta, System.currentTimeMillis());
            } catch (InterruptedException | IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void init() {
        addKeyListener(new KeyInputHandler());
        random = new Random();

        try {
            Register.register();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


//        for(wall : walls);
    }

    public void render(long time) {
        BufferStrategy bs = getBufferStrategy();
        if (bs == null) {
            createBufferStrategy(2);
            requestFocus();
            return;
        }

        Graphics g = bs.getDrawGraphics(); //ïîëó÷àåì Graphics èç ñîçäàííîé íàìè BufferStrategy
        Image image = Register.GRASS;
        for (int y = -WORLD_HEIGHT / 2; y < WORLD_HEIGHT / 2; y += (int) (32)) {
            for (int x = -WORLD_WIDTH / 2; x < WORLD_WIDTH / 2; x += (int) (32)) {
                g.drawImage(image,
                        (int) (Game.WIDTH / 2 + (x - PLAYER.posX)*k),
                        (int) (Game.HEIGHT / 2 + (y - PLAYER.posY)*k),
                        (int) (Game.WIDTH / 2 + (x - PLAYER.posX)*k+ 32*k) ,
                        (int) (Game.HEIGHT / 2 + (y - PLAYER.posY)*k+ 32*k),
                        0, 0,
                        image.getWidth(null),
                        image.getHeight(null),
                        null);
            }
        }



        for (ArrayList<LivingEntity> arrayList : ENTITIES) {
            for (LivingEntity entities : arrayList) {
                healthDisplay(g,entities);
                if (debug) {
                    debugger(g, entities);
                }
                animation(entities, time, g);
            }
        }
        for (Player player : Register.PLAYERS) {
            healthDisplay(g, player);
            if (debug) {
                debugger(g, player);
            }
            if (!player.playerRide) {
                if (player.turn == 0) {
                    player.drawPlayer(g, player.stay);

                } else {
                    if (time % 500 >= 250) {
                        if (player.turn > 0) {
                            player.drawPlayer(g, player.right);
                        } else {
                            player.drawPlayer(g, player.left);
                        }
                    }

                    if (time % 500 < 250) {
                        if (player.turn > 0) {
                            player.drawPlayer(g, player.stepRight);
                        } else {
                            player.drawPlayer(g, player.stepLeft);
                        }
                    }
                }
            } else if (player.playerRideOn != null){
                if (player.turn == 0) {
                    player.drawPlayer(g, player.left);
                    player.playerRideOn.drawRideOn(g, player.playerRideOn.stay, player, -8, -4);
                } else {
                    if (time % 500 >= 250) {
                        if (player.turn > 0) {
                            player.drawPlayer(g, player.right);
                            player.playerRideOn.drawRideOn(g, player.playerRideOn.right, player, 8, -4);
                        } else {
                            player.drawPlayer(g, player.left);
                            player.playerRideOn.drawRideOn(g, player.playerRideOn.left, player, -8 ,-4);
                        }
                    }

                    if (time % 500 < 250) {
                        if (player.turn > 0) {
                            player.drawPlayer(g, player.right);
                            player.playerRideOn.drawRideOn(g, player.playerRideOn.stepRight, player,8,-4);
                        } else {
                            player.drawPlayer(g, player.left);
                            player.playerRideOn.drawRideOn(g, player.playerRideOn.stepLeft, player,-8,-4);
                        }
                    }
                }
            }
        }
        for (ProjectileEntity entities : Register.PROJECTILE_ENTITIES) {
            if (debug) {
                //debagger(g, entities);
            }
            if (entities.turn > 0) {
                entities.drawPartAnimation(g, entities.right);
            } else {
                entities.drawPartAnimation(g, entities.left);
            }
        }



        for (AbstractEntity wall : Register.WALLS) {
            wall.draw(g, (int) wall.boxX1, (int) wall.boxY1, (int) wall.boxX2, (int) wall.boxY2);
        }

        g.dispose();
        bs.show(); //ïîêàçàòü
    }

    public void update(long delta, long time) throws InterruptedException, IOException {
        PLAYER.update();

        if (randInt(0,1000) <= 2 && PIGS.size() <= 10) {
            PIGS.add(new Pig(randInt(-WORLD_WIDTH / 2, WORLD_WIDTH / 2),
                    randInt(-WORLD_HEIGHT / 2, WORLD_HEIGHT / 2)));
        }
        if (randInt(0,1000) <= 20 && HORSES.size() <= 10) {
            HORSES.add(new Horse(randInt(-WORLD_WIDTH / 2, WORLD_WIDTH / 2),
                    randInt(-WORLD_HEIGHT / 2, WORLD_HEIGHT / 2)));
        }

        for (ArrayList<LivingEntity> arrayList : ENTITIES) {
            for (LivingEntity entities : arrayList) {
                entities.update();
            }
        }
        for (ArrayList<LivingEntity> arrayList : FUTURES) {
            for (LivingEntity entities : arrayList) {
                entities.update();
            }
        }





        Thread.sleep(48);


    }





    public static void main(String[] args) {

        Game game = new Game();
        game.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        JFrame frame = new JFrame(Game.NAME);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.add(game, BorderLayout.CENTER);
        frame.pack();
        frame.setResizable(true);
        frame.setVisible(true);



        game.start();
    }
    static class KeyInputHandler extends KeyAdapter {
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                VK_LEFT = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                VK_RIGHT = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_UP) {
                VK_UP = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                VK_DOWN = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_A) {
                VK_A = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_D) {
                VK_D = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_W) {
                VK_W = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_S) {
                VK_S = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_F3) {
                debug = !debug;
            }
            if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
                ACCELERATION = true;
            }
            if (e.getKeyCode() == KeyEvent.VK_R) {
                RIDE = true;
            }
        }

        public void keyReleased(KeyEvent e) {

            if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                VK_LEFT = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                VK_RIGHT = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_UP) {
                VK_UP = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                VK_DOWN = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_A) {
                VK_A = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_D) {
                VK_D = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_W) {
                VK_W = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_S) {
                VK_S = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
                ACCELERATION = false;
            }
            if (e.getKeyCode() == KeyEvent.VK_R) {
                RIDE = false;
            }
        }
    }
    /*public static void main(final String[] args) {
        // Schedule a job for the event-dispatching thread:
        // creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Game().show();
            }
        });
    }*/
    public int transformToRenderX (double posX) {
        return (int) (Game.WIDTH / 2 + (posX - PLAYER.posX) * k);
    }
    public int transformToRenderY (double posY) {
        return (int) (Game.HEIGHT / 2 + (posY - PLAYER.posY) * k);
    }
    private void debugger(Graphics g, LivingEntity entities) {
        g.drawLine(transformToRenderX(entities.boxX1),
                transformToRenderY(entities.boxY1),
                transformToRenderX(entities.boxX2),
                transformToRenderY(entities.boxY1));
        g.drawLine(transformToRenderX(entities.boxX2),
                transformToRenderY(entities.boxY1),
                transformToRenderX(entities.boxX2),
                transformToRenderY(entities.boxY2));
        g.drawLine(transformToRenderX(entities.boxX2),
                transformToRenderY(entities.boxY2),
                transformToRenderX(entities.boxX1),
                transformToRenderY(entities.boxY2));
        g.drawLine(transformToRenderX(entities.boxX1),
                transformToRenderY(entities.boxY2),
                transformToRenderX(entities.boxX1),
                transformToRenderY(entities.boxY1));
        if (entities.toPosX != 0 && entities.toPosY != 0) {
            g.drawLine(transformToRenderX(entities.posX),
                    transformToRenderY(entities.posY),
                    transformToRenderX(entities.toPosX),
                    transformToRenderY(entities.toPosY));
        }


    }
    public void healthDisplay (Graphics g,LivingEntity entities) {
        g.setColor(Color.RED);
        double i = (20 - entities.boxX2 + entities.boxX1) / 2;
        g.fillPolygon(

                new int[]{transformToRenderX(entities.boxX1 - i),
                        transformToRenderX(entities.boxX1 - i + entities.health),
                        transformToRenderX(entities.boxX1 - i + entities.health),
                        transformToRenderX(entities.boxX1 - i)},
                new int[]{transformToRenderY(entities.boxY1 -6),
                        transformToRenderY(entities.boxY1 -6),
                        transformToRenderY(entities.boxY1 -10),
                        transformToRenderY(entities.boxY1 -10)},
                4);
    }

    public void animation (LivingEntity entity, long time, Graphics g) {
        if (entity.turn == 0) {
            entity.drawPartAnimation(g, entity.stay);

        } else {
            if (time % 500 >= 250) {
                if (entity.turn > 0) {
                    entity.drawPartAnimation(g, entity.right);
                } else {
                    entity.drawPartAnimation(g, entity.left);
                }
            }

            if (time % 500 < 250) {
                if (entity.turn > 0) {
                    entity.drawPartAnimation(g, entity.stepRight);
                } else {
                    entity.drawPartAnimation(g, entity.stepLeft);
                }
            }
        }
    }

}